#ifndef _COMPLEXVEC_
#define _COMPLEXVEC_

#include "complex.h"
#include <vl/VLd.h>
#include <vector>

using namespace std;

namespace moremath{

	class Matc;

	class Vecc{
	protected:
		vector<complex> mVec;
		int mNumElts;
	public:
		Vecc(Vecd _re, Vecd _im){
			mNumElts = _re.Elts();
			mVec.resize(mNumElts);
			for(int i=0; i<mNumElts; i++){
				mVec[i] = complex(_re[i], _im[i]);
			}
		}
		Vecc(Vecd _re){
			mNumElts = _re.Elts();
			mVec.resize(mNumElts);
			for(int i=0; i<mNumElts; i++){
				mVec[i] = complex(_re[i], 0);
			}
		}
		Vecc(int _size){
			mNumElts=_size;
			mVec.resize(_size);
		}
		Vecc(){
			mNumElts=1;
			mVec.resize(mNumElts);
		}

		Vecd re();
		Vecd im();
		void setReal(Vecd &_real);
		void setImag(Vecd &_imag);
		inline int Elts(){return mNumElts;}
		inline void SetSize(int _s){
			mNumElts=_s;
			mVec.resize(_s);
		}

		inline complex& operator[] (int i){return mVec[i];}	// indexing operator
		void operator = (Vecc _v);	// assign one to other
		Vecc operator + (Vecc& _v);
		void operator += (Vecc& _v);
		Vecc operator - ();
		Vecc operator - (Vecc &_v);
		Vecc operator * (double);	// multiplies with a scalar
		Vecc operator * (complex _q);	// multiplies with a complex num
		Vecc operator * (Vecc &_v);	// multiplies pairwise with a Vecc
		Vecc operator * (Vecd &_v);	// multiplies pairwise with a Vecd
		void operator *= (double);	// multiplies with a scalar
		void operator *= (Vecc& _v);
		Vecc operator / (double);	// divides by a number
		Vecc operator / (complex _c);	// divide by complex number
		Vecc operator / (Vecc &_v);	// pairwise divides by a vec

		double norm();	// returns the norm
		Vecc conj();	// returns the complex conjugate

		// pairwise vector element and matrix row multiplication
		Matc operator * (Matc &_m);
	};

}

ostream& operator <<(ostream &out, moremath::Vecc &_v);
moremath::Vecc exp(moremath::Vecc _v);
moremath::Vecc sqrt(moremath::Vecc _v);
moremath::complex cdot(moremath::Vecc v1, moremath::Vecc v2);	// complex dot prod of complex vectors
moremath::complex cdot(moremath::Vecc v1, Vecd v2);
moremath::complex cdot(Vecd v2, moremath::Vecc v1);

#endif
